//
//  LBHueFilter.mm
//  OpenGLGame
//
//  Created by Nguyen Cong Huy on 3/29/13.
//  Copyright (c) 2013 UIT. All rights reserved.
//

#include "LBHueFilter.h"
#include "LBGraphics.h"

char fShaderStrHue[] = ""
"precision mediump float;"

"varying vec2 vtexCoor;"
"varying vec4 vposition;"
"uniform sampler2D texture;"
"uniform float hue;"


// hue function
"vec4 hueColor(vec4 color, float hueAdjust){"
"   float PI = 3.141592654;"
"   hueAdjust = hueAdjust*PI/180.0;"

"   const highp  vec4  kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);"
"   const highp  vec4  kRGBToI     = vec4 (0.595716, -0.274453, -0.321263, 0.0);"
"   const highp  vec4  kRGBToQ     = vec4 (0.211456, -0.522591, 0.31135, 0.0);"

"   const highp  vec4  kYIQToR   = vec4 (1.0, 0.9563, 0.6210, 0.0);"
"   const highp  vec4  kYIQToG   = vec4 (1.0, -0.2721, -0.6474, 0.0);"
"   const highp  vec4  kYIQToB   = vec4 (1.0, -1.1070, 1.7046, 0.0);"

// Convert to YIQ
"   highp float   YPrime  = dot (color, kRGBToYPrime);"
"   highp float   I      = dot (color, kRGBToI);"
"   highp float   Q      = dot (color, kRGBToQ);"

// Calculate the hue and chroma
"   highp float   hue     = atan (Q, I);"
"   highp float   chroma  = sqrt (I * I + Q * Q);"

// Make the user's adjustments
"   hue += (hueAdjust);" //why negative rotation?

// Convert back to YIQ
"   Q = chroma * sin (hue);"
"   I = chroma * cos (hue);"

// Convert back to RGB
"   highp vec4    yIQ   = vec4 (YPrime, I, Q, 0.0);"
"   color.r = dot (yIQ, kYIQToR);"
"   color.g = dot (yIQ, kYIQToG);"
"   color.b = dot (yIQ, kYIQToB);"

// Save the result
"   return color;"
"}"
// END hue function


"void main()"
"{"
"    lowp vec4 textureColor = texture2D(texture, vtexCoor);"
"    textureColor = hueColor(textureColor, hue);"
"    gl_FragColor = textureColor;"
"}";

LBHueFilter::LBHueFilter(){
    init(0, fShaderStrHue);
    LBGraphics::getInstance()->useProgram(program);
    hueUniform = program->uniformIndex("hue");
    setHue(1.0f);
}

void LBHueFilter::setHue(float hue){
    this->hue = hue;
    LBGraphics::getInstance()->useProgram(program);
    glUniform1f(hueUniform, hue);
}